#include "../DistortMap.fxh"

#include "ShadowMap.fxh"

uniform const float specularPower	= 16;
uniform const float specularIntensity	= 1;
uniform const float3 ambientLightColor	= float3(0.5,0.5,0.5);
uniform const float3 Light1Color	= float3(1,1,1);
uniform const float3 Light1Direction;
uniform const float FogNear	= 360;
uniform const float FogFar	= 1080;
uniform const float3 FogColor	= float3(0.5,0.5,0.6);

float3 Rim_Color = float3(0.5,0.5,0.5);
uniform const float RimIntensity = 0.3f;
uniform const float Rim_Start = 0.3f;
uniform const float Rim_End = 1.0f;

uniform const float2 halfPixel;
uniform const float2 ScreenSize;

uniform const float4x4 View;
uniform const float4x4 invProjection;


uniform const float4 EnvironmentSH[9] : SPHERICALHARMONIC;
float3 SampleSH(float3 normal)
{
	float3 light = 
		EnvironmentSH[0].xyz + 
		EnvironmentSH[1].xyz * normal.x +  
		EnvironmentSH[2].xyz * normal.y + 
		EnvironmentSH[3].xyz * normal.z + 
		EnvironmentSH[4].xyz * (normal.x * normal.y) +
		EnvironmentSH[5].xyz * (normal.y * normal.z) + 
		EnvironmentSH[6].xyz * (normal.x * normal.z) + 
		EnvironmentSH[7].xyz * ((normal.z * normal.z) - (1.0f / 3.0f)) + 
		EnvironmentSH[8].xyz * ((normal.x * normal.x) - (normal.y * normal.y));
	return max(0,light);
}


uniform const texture colorMap;
uniform const texture normalMap;
uniform const texture depthMap;
uniform const texture lightMap;

sampler colorSampler = sampler_state
{
	Texture = (colorMap);
	AddressU = CLAMP;
	AddressV = CLAMP;
	MagFilter = LINEAR;
	MinFilter = LINEAR;
	Mipfilter = LINEAR;
};

sampler normalSampler = sampler_state
{
	Texture = (normalMap);
	AddressU = CLAMP;
	AddressV = CLAMP;
	MagFilter = LINEAR;
	MinFilter = LINEAR;
	Mipfilter = LINEAR;
};

sampler depthSampler = sampler_state
{
	Texture = (depthMap);
	AddressU = CLAMP;
	AddressV = CLAMP;
	MagFilter = LINEAR;
	MinFilter = LINEAR;
	Mipfilter = LINEAR;
};

sampler lightSampler = sampler_state
{
	Texture = (lightMap);
	AddressU = CLAMP;
	AddressV = CLAMP;
	MagFilter = LINEAR;
	MinFilter = LINEAR;
	Mipfilter = LINEAR;
};

struct VertexShaderInput
{
	float3 Position : POSITION0;
	float2 TexCoord : TEXCOORD0;
};

struct VertexShaderOutput
{
	float4 Position : POSITION0;
	float2 TexCoord : TEXCOORD0;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
	VertexShaderOutput output;
	output.Position = float4(input.Position,1);
	output.TexCoord = input.TexCoord;
	return output;
}


float ComputeFogFactor(float d,float N,float F)
{
	return clamp((d - N) / (F - N),0,1);
}

float4 PShader2(float2 inuv : TEXCOORD0,float2 screenPos : VPOS) : COLOR0
{
	float2 uv = inuv + halfPixel;

	float4 color	= tex2D(colorSampler,uv);
	clip(color.a - 0.8);

	float3 lightDir	= normalize(mul(Light1Direction,View));
	float4 normalSpec	= tex2D(normalSampler,uv);
	float3 normal	= (normalSpec.xyz * 2) - 1;

	float diffuse	= max(0,dot(normal,-lightDir));

	float depth	= tex2D(depthSampler,uv).x;
	float3 viewPos;
	viewPos.z	= depth;
	viewPos.xy	= -depth * ((screenPos / (float2(0.5,-0.5) * ScreenSize)) + float2(-1,1));
	viewPos.xy	= mul(viewPos.xy,invProjection);

	float3 viewDirection	= normalize(viewPos);
	float specular	=  dot(reflect(lightDir,normal),viewDirection);
	specular = normalSpec.w * specularIntensity * pow(specular,specularPower);

	float3 light	= Light1Color * (diffuse + specular);

	viewPos	= mul(float4(viewPos,1),lightMatrix);
	viewPos	= Distort(lightMatrix,viewPos);

	float2 shadowCoord	= mul(float4(viewPos,1),textureScaleBias).xy;
	if(shadowCoord.x >= 0 && shadowCoord.x <= 1 && shadowCoord.y >= 0 && shadowCoord.y <= 1)
	{
		light	*= CalcShadowTermSoftPCF3X(viewPos.z,shadowCoord.xy,shadowMapSampler);
	}

	light	+= ambientLightColor * SampleSH(normal);


	color.rgb	*= light;
	color.rgb	+= Rim_Color * smoothstep(Rim_Start,Rim_End,1 - dot(-normal,viewDirection)) * RimIntensity;
	color.rgb	= lerp(color.rgb,FogColor,ComputeFogFactor(-depth,FogNear,FogFar));
	return float4(color.rgb,1);
}

technique AntiAliasingStalker
{
	pass Pass1
	{
		VertexShader = compile vs_3_0 VertexShaderFunction();
		PixelShader = compile ps_3_0 PShader2();
	}
}



